package com.ccl.iot.monitor;

import com.ccl.iot.publics.XCoreKernel;

public abstract class MotionMonitor extends Monitor {
	public interface OnMotionListener extends MonitorListener{
		public void onMotion(MotionMonitor aMonitor, boolean aActing);
	}
	
	/*
	 * 	Non-static functions
	 */
	private String iName = "Motion";
	private Object iWaitLock = new Object();
	
	private long iActionTimeout = 500;
	
	private volatile boolean iActing = false;
	private volatile long iLastActionTime = 0;
	
	MotionMonitor(String aName){
		if (aName != null){
			iName = aName;
		}
	}
	
	public void setActionTimeout(long aTimeout){
		iActionTimeout = aTimeout;
	}
	
	@Override
	public boolean startMonitor(){
		if (super.startMonitor()){
			new Thread(new Runnable(){
				@Override
				public void run() {
					boolean tActing = false;
					long tLastActionTime = XCoreKernel.SYSTICKCOUNT();
					
					Thread.currentThread().setName(iName +" monitor thread");
					
					while(isMonitoring()){
						if (tActing != iActing){
							tActing = iActing;
							
							if (getListenerCount() > 0){
								int tIndex = 0;
								OnMotionListener tListener;
								
								tListener = (OnMotionListener) getFirstListener();
								while(tListener != null){
									tListener.onMotion(MotionMonitor.this, tActing);
									tListener = (OnMotionListener) getNextListener(tIndex++);
								}
							}
						}else{
							synchronized(iWaitLock){
								try {
									if (tActing){
										iWaitLock.wait(500);
										
										if (iActing){
											tLastActionTime = XCoreKernel.SYSTICKCOUNT();
											if (XCoreKernel.GetTickInterval(iLastActionTime, tLastActionTime) >= iActionTimeout){
												iActing = false;
												iLastActionTime = tLastActionTime;
												
												onMotionTimeout();
											}
										}
									}else{
										iWaitLock.wait();
									}
								} catch (InterruptedException e) {
								}
							}
						}
					}
				}
			}).start();
			
			return true;
		}
		
		return false;
	}
	
	@Override
	public boolean stopMonitor(boolean aForce){
		if (super.stopMonitor(aForce)){
			synchronized(iWaitLock){
				iWaitLock.notify();
			}
			
			return true;
		}
		
		return false;
	}
	
	public boolean isMotionActing(){
		if (super.isMonitoring()){
			return iActing;
		}
		
		return false;
	}
	
	protected abstract void onMotionTimeout();
	
	protected void onMotionAction(boolean aActing){
		iLastActionTime = XCoreKernel.SYSTICKCOUNT();
		
		if (aActing != iActing){
			iActing = aActing;
			
			synchronized(iWaitLock){
				iWaitLock.notify();
			}
		}
	}
}
